package yao.spider.jsoup.vobao;

import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.BlockingQueue;

import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import yao.spider.jsoup.common.CommonConsTants;
import yao.spider.jsoup.common.MyDateUtils;
import yao.spider.jsoup.vobao.bean.Answer;
import yao.spider.jsoup.vobao.bean.Question;

/**
 * 答案爬取（消费者）
 * 
 * @author chenyao
 * @date 2017年2月28日 下午5:47:42
 */
public class QuestionCrawler implements Runnable {

	private final BlockingQueue<Question> urlQueue;
	private final ResultHandler handler;

	public QuestionCrawler(BlockingQueue<Question> urlQueue, ResultHandler handler) {
		super();
		this.urlQueue = urlQueue;
		this.handler = handler;
	}

	@Override
	public void run() {
		while (true) {
			try {
				crawlAndSave(urlQueue.take());
			} catch (InterruptedException e) {
				Thread.currentThread().interrupt();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}	
	}

	private Document craw(String url) {
		Document document = null;
		try {
			document = Jsoup.connect(url).header("Accept", "*/*").header("Accept-Encoding", "gzip, deflate")
					.header("Accept-Language", "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3")
					.header("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:48.0) Gecko/20100101 Firefox/48.0")
					.timeout(CommonConsTants.TIME_OUT_MS).get();
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
		return document;
	}

	private void crawlAndSave(Question q) throws InterruptedException {
		System.out.println("start=" + q.getUrl());
		Document document = this.craw(q.getUrl());
		Question question = createQuestion(document, q);
		Elements pageNums = document.select(".fenye");
		if (pageNums != null && pageNums.size() > 0) {
			appendAnswers(question, document);
		}
		System.out.println("find:" + question.toString());
		handler.exec(question);
	}

	private void appendAnswers(Question question, Document document) {
		List<Map<String, String>> postDatas = this.getOtherAnswerPostData(document);		
		for(Map<String, String> data : postDatas) {
			question.getAnswers().addAll(this.createAnswersByPost(data));
		}
	}
	

	private List<Map<String, String>> getOtherAnswerPostData(Document document) {
		List<Map<String, String>> datas = Lists.newArrayList();
		String totalPages_str = document.select("input[name='Search.TotalPages']").get(0).val();
		int totalPages = Integer.parseInt(totalPages_str);
		if(totalPages <= 1) {
			return datas;
		}
		
		String orderName_str = document.select("input[name='Search.OrderName']").get(0).val();
		String tabType_str = document.select("input[name='Search.TabType']").get(0).val();
		String questionId_str = document.select("input[name='Search.QuestionId']").get(0).val();
		String pageSize_str = document.select("input[name='Search.PageSize']").get(0).val();
		String lastHash_str = document.select("input[name='Search.LastHash']").get(0).val();
		String totalCount_str = document.select("input[name='Search.TotalCount']").get(0).val();

		for(int i=2; i <= totalPages; i++) {			
			Map<String, String> data = Maps.newHashMap();
			data.put("Search.OrderName", orderName_str);
			data.put("Search.TabType", tabType_str);
			data.put("Search.QuestionId", questionId_str);
			data.put("Search.PageIndex", String.valueOf(i));
			data.put("Search.PageSize", pageSize_str);
			data.put("Search.LastHash", lastHash_str);
			data.put("Search.TotalPages", totalPages_str);
			data.put("Search.TotalCount", totalCount_str);
			
			datas.add(data);
		}
		return datas;
	}
	

	private Question createQuestion(Document doc, Question part) {
		Question question = new Question();
		String title = StringUtils.trim(doc.select(".pagetit .pname").get(0).text());
		question.setTitle(title);
		String time_str = StringUtils.trim(doc.select(".pagetit .ptime").get(0).text());
		question.setQuestionDate(MyDateUtils.parseDate(time_str, "yyyy/MM/dd hh:mm:ss"));
		question.setTags(this.createTags(doc));
		question.setAnswers(this.createAnswers(doc));
		question.setUrl(part.getUrl());
		question.setCategory(part.getCategory());
		return question;
	}
	
	private List<String> createTags(Document doc) {
		List<String> tags = Lists.newArrayList();
		Elements tags_a = doc.select(".ptagsl li a");
		for(Element a : tags_a) {
			tags.add(a.text());
		}
		return tags;
	}
	
	private List<Answer> createAnswersByPost(Map<String, String> postData) {
		Document post = null;
		try {
			post = Jsoup.connect(Constants.POST_ANSWER_URL).timeout(CommonConsTants.TIME_OUT_MS)
			.header("Content-Type", "text/html; charset=utf-8")
			.data(postData)
			.post();
		} catch (IOException e) {
			e.printStackTrace();
			return Lists.newArrayList();
		}
		return this.createAnswers(post);		
	}

	private List<Answer> createAnswers(Document doc) {
		List<Answer> answers = Lists.newArrayList();
		Elements lis = doc.select(".pagetop");
		if(lis == null || lis.isEmpty()) {
			return answers;
		}
		for(Element li : lis) {
			Answer answer = new Answer();
			Elements content_eles = li.select(".ptopcon");
			if(content_eles != null && content_eles.size() > 0) {
				String content = content_eles.get(0).text();
				answer.setContent(content);
			}
			Elements p3_all = li.select(".pdate");
			if(p3_all != null && p3_all.size() > 0) {
				String time_str = p3_all.get(0).text().replaceAll("回答时间：", "").trim();
				Date answerTime = MyDateUtils.parseDate(time_str, "yyyy/MM/dd hh:mm:ss");
				answer.setAnswerTime(answerTime);
			}
			if(!answer.empty()) {
				answers.add(answer);
			}
		}
		return answers;
	}

	

}
